package com.lyz.myself.config.shiro;

import com.lyz.myself.config.shiro.jwt.JwtToken;
import com.lyz.myself.config.utils.JedisUtil;
import com.lyz.myself.config.utils.JwtUtil;
import com.lyz.myself.config.utils.common.StringUtil;
import com.lyz.myself.config.utils.util.EmptyUtils;
import com.lyz.myself.config.utils.util.LogUtils;
import com.lyz.myself.config.utils.util.WebUtil;
import com.lyz.myself.mapper.UserMapper;
import com.lyz.myself.pojo.Po.Position;
import com.lyz.myself.pojo.Po.Role;
import com.lyz.myself.pojo.Po.User;
import com.lyz.myself.pojo.Po.common.Constant;
import com.lyz.myself.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpSession;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class CustomRealm extends AuthorizingRealm {
    Logger log = LogUtils.getExceptionLogger();
    @Autowired
    private UserService userService;

    /**
     * 大坑，必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 获取身份验证信息
     * Shiro中，最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
     *
     * @param authenticationToken 用户身份信息 token
     * @return 返回封装了用户信息的 AuthenticationInfo 实例
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("————身份认证方法————");
        String token = (String) authenticationToken.getCredentials();
        // 解密获得NAME，用于和数据库进行对比
        String userName = JwtUtil.getClaim(token, Constant.NAME);
        // 帐号为空
        if (StringUtil.isBlank(userName)) {
            throw new AuthenticationException("Token中帐号为空");
        }
        // 从数据库获取对应用户名密码的用户
        User user = userService.selectByPrimaryKey(Integer.valueOf(userName));
        if (user == null) {
            throw new AuthenticationException("该帐号不存在");
        }
        // 开始认证，要AccessToken认证通过，且Redis中存在RefreshToken，且两个Token时间戳一致
        if (JwtUtil.verify(token) && JedisUtil.exists(Constant.PREFIX_SHIRO_REFRESH_TOKEN + userName)) {
            // 获取RefreshToken的时间戳
            String currentTimeMillisRedis = JedisUtil.getObject(Constant.PREFIX_SHIRO_REFRESH_TOKEN + userName).toString();
            // 获取AccessToken时间戳，与RefreshToken的时间戳对比
            if (JwtUtil.getClaim(token, Constant.CURRENT_TIME_MILLIS).equals(currentTimeMillisRedis)) {
                return new SimpleAuthenticationInfo(token, token, "customRealm");
            }
        }
        throw new AuthenticationException("登录已过期");
    }

    /**
     * 获取授权信息(获取当前用户)
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("————权限认证————");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String userName = JwtUtil.getClaim(principalCollection.toString(), Constant.NAME);
        // 从数据库获取对应用户名密码的用户
        User user = userService.selectByPrimaryKey(Integer.valueOf(userName));
        //获取用户角色
        List<Role> roles =this.userService.getRole(user.getUser_id());
        if(roles.size()>0){
            List<Position> position =this.userService.getPosition(roles.get(0).getPosition_id());
            //添加角色
            for(Position p : position){
                authorizationInfo.addRole(p.getName());
            }
        }
        //表结构是有问题的
        //添加权限
        for(Role role : roles){
            authorizationInfo.addStringPermission(role.getPosition_id()+"");
        }
        return authorizationInfo;
    }
}
